#pragma once
#include <iostream>
#include "utility/index.hpp"
#include "request_access/index.hpp"
#include "data_access/index.hpp"
#include "components/index.hpp"
#include "actions.hpp"

using namespace std;
using namespace utility;

namespace components2 {
    class ProductCompleteOrder : public components::EntityRequest {
    public:
        COMPONENT_INSTANCE_FUNCTION(ProductCompleteOrder);

        ProductCompleteOrder();

        any UpdateStatus();

        any Update2();

        any CancelReview();

        any GetProductCompleteOrder();

    private:
        EntityData getProductCompleteOrderEntity(EntityData &dict);

        vector<EntityData> getSaleComplete(const any &saleOrderId, const any &completeOrderId);

        entity_access::EntityType *saleOrderEntity;
        entity_access::EntityType *viewProductCompleteOrderEntity;
        entity_access::EntityType *saleProductAccessoryEntity;
    };

    ProductCompleteOrder::ProductCompleteOrder() {
        SET_METHOD_ACTION(UpdateStatus);
        SET_METHOD_ACTION(Update2);
        SET_METHOD_ACTION(CancelReview);
        SET_METHOD_ACTION(GetProductCompleteOrder);
        saleOrderEntity = entity_access::GetEntityType("SaleOrder");
        viewProductCompleteOrderEntity = entity_access::GetEntityType("ViewProductCompleteOrder");
        saleProductAccessoryEntity = entity_access::GetEntityType("SaleProductAccessory");
    }

    std::any ProductCompleteOrder::UpdateStatus() {
        EntityData dict = Request->RequestEntity.GetEntityData(Entity->Name);

        auto oldEntityData = SelectEntityByPrimaryKey(QueryRequest->PrimaryKeyValue);
        if (oldEntityData.Empty()) return Request->GetMessageMap("产品完成单不存在");

        auto msg = CompareVersion(dict, oldEntityData);
        if (!msg.empty()) return Request->GetMessageMap(msg);

        bool blSucceed = true;
        try {
            DataBase->BeginTransaction();

            blSucceed = Actions::UpdateStatusAndReview(shared_from_this(), nullptr, dict, 6);

            if (blSucceed) DataBase->CommitTransaction();
            else DataBase->RollbackTransaction();
        } catch (const std::exception &e) {
            DataBase->RollbackTransaction();
            throw MessageException(e.what(), "");
        }

        return GetSucceedMap(blSucceed);
    }

    any ProductCompleteOrder::Update2() {
        auto dict = Request->RequestEntity.GetEntityData(Entity->Name);
        auto completeOrder = getProductCompleteOrderEntity(dict);

        auto details = completeOrder.GetEntityDataList("Details");
        if (details.empty()) return Request->GetMessageMap("产品明细完成数量不能都为0");

        auto oldEntityData = SelectEntityByPrimaryKey(saleOrderEntity, dict.Get("SaleOrderId"));
        if (oldEntityData.Empty()) return Request->GetMessageMap("销售订单不存在");

        EntityData saleOrder;
        saleOrder["RowVersion"] = dict.Get("SaleRowVersion");

        auto msg = CompareVersion(saleOrder, oldEntityData);
        if (!msg.empty()) return Request->GetMessageMap(msg);

        Request->RequestEntity["ProductCompleteOrder"] = completeOrder;
        auto obj = Update();

        if (obj.ContainsKey("Succeed")) {
            EntityData updateEntityData;
            updateEntityData["UpdateDate"] = DateTime();
            updateEntityData["UpdateUser"] = Request->OperationUser;

            UpdateEntity(saleOrderEntity, GetQueryByPrimaryKey(saleOrderEntity, dict.Get("SaleOrderId")), updateEntityData);
        }

        return obj;
    }

    EntityData ProductCompleteOrder::getProductCompleteOrderEntity(EntityData &dict) {
        EntityData data;

        data["CompleteOrderId"] = dict["CompleteOrderId"];
        data["CompleteDate"] = dict["CompleteDate"];
        data["ProduceEmployeeId"] = dict["ProduceEmployeeId"];
        data["Remark"] = dict["Remark"];
        data["CreateUser"] = Request->OperationUser;
        data["RowVersion"] =  dict["RowVersion"];

        auto details = dict.GetEntityDataList("Details");

        vector<EntityData> detailList;
        for (auto &d: details) {
            auto num = d.GetFloat("Num");
            if (num != 0) {
                EntityData detail;
                detail["Num"] = d["Num"];
                detail["DisplayIndex"] = d["DisplayIndex"];
                detail["ProductId"] = d["ProductId"];
                detailList.emplace_back(detail);
            }
        }

        data["Details"] = detailList;

        return data;
    }

    any ProductCompleteOrder::CancelReview() {
        Actions::SetCancelReviewEntityData(shared_from_this());
        return UpdateStatus();
    }

    any ProductCompleteOrder::GetProductCompleteOrder() {
        EntityData entityData = SelectEntityByPrimaryKey(viewProductCompleteOrderEntity, QueryRequest->PrimaryKeyValue);
        entityData.Remove("IsDelete");
        if (!entityData.Empty()) {
            auto details=  getSaleComplete(entityData.Get("SaleOrderId"), entityData.Get("CompleteOrderId"));

            for (auto &item: details) {
                auto list = components::EntityByComplexTypeOperation::GetComplexTypeDataList(shared_from_this(), saleProductAccessoryEntity, "SaleDetailId", item.Get("SaleDetailId"));
                item["AccessoryDetails"]=list;
            }

            entityData["Details"] =details;
        }

        return entityData;
    }

    vector<EntityData> ProductCompleteOrder::getSaleComplete(const any &saleOrderId, const any &completeOrderId) {
        auto parameters = make_shared<data_access::DataParameters>();
        parameters->Add("@SaleOrderId", saleOrderId);
        parameters->Add("@CompleteOrderId", completeOrderId);

        auto query = make_shared<data_access::Query>();
        string sql = "with SaleComplete as\n"
                     "(\n"
                     "SELECT SaleOrderId,a.ProductId, sum(Num) CompletedNum FROM t_productcompleteorder_detail a,t_productcompleteorder b\n"
                     "where b.IsDelete=0 and a.CompleteOrderId=b.CompleteOrderId and b.SaleOrderId=@SaleOrderId and b.CompleteOrderId<>@CompleteOrderId\n"
                     "group by SaleOrderId,a.ProductId\n"
                     "),\n"
                     "SaleCompleteDetail as\n"
                     "(\n"
                     "select a.*,ifnull(b.CompletedNum,0) CompletedNum,a.Num-ifnull(b.CompletedNum,0) BalanceNum,c.Status,d.Name ProductTypeName,e.Name ProductName,e.Area,e.Spec from t_SaleOrder_Detail a\n"
                     "inner join t_saleorder c on a.SaleOrderId=c.SaleOrderId \n"
                     "left join SaleComplete b on a.SaleOrderId=b.SaleOrderId and a.ProductId=b.ProductId\n"
                     "left join t_product e on a.ProductId=e.ProductId\n"
                     "left join t_producttype d on e.ProductTypeId=d.ProductTypeId \n"
                     "where a.SaleOrderId=@SaleOrderId\n"
                     ")\n"
                     "select SaleDetailId, SaleOrderId,ProductTypeName,a.ProductId,ProductName,a.Area,a.Spec,a.Remark,a.Num SaleNum,CompletedNum+ifnull(f.Num,0) CompletedNum,BalanceNum,ifnull(f.Num,0) Num from \n"
                     "SaleCompleteDetail a\n"
                     "left join t_productcompleteorder_detail f on a.ProductId=f.ProductId and f.CompleteOrderId=@CompleteOrderId\n"
                     "where a.BalanceNum<>0 \n"
                     "order by a.DisplayIndex";

        query->SetSql(sql, parameters);

        return SelectEntities(query);
    }
}